package util

import (
	"fmt"
	"log"
	"net"
	"sync"
)

func Listen(port int, listenPorts map[int]net.Listener, mutex *sync.Mutex, allPortTable *map[int]string) {
	listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
	if err != nil {
		log.Println("listen port failed: ", port, err)
		return
	}
	log.Println("listen port: ", port)
	mutex.Lock()
	listenPorts[port] = listener
	mutex.Unlock()
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println("connect failed ：", err)
			break
		}
		remoteAddr := conn.RemoteAddr().(*net.TCPAddr)
		ip := remoteAddr.IP.String()
		log.Println("connect and close from remote ip: " + ip)
		host, exist := (*allPortTable)[port]
		if exist {
			go handleTcpProxy(conn, host, port)
		} else {
			conn.Close()
		}
	}

}

/**
  转发TCP数据请求
*/
func handleTcpProxy(clientConn net.Conn, host string, port int) {
	targetConn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", host, port))
	if err != nil {
		log.Printf("Failed to connect to target server: %v\n", err)
		clientConn.Close()
		return
	}
	defer targetConn.Close()

	// 获取客户端的请求数据，将数据发送给目标
	go func() {
		buf := make([]byte, 1024)
		for {
			n, err := clientConn.Read(buf)
			if err != nil {
				log.Printf("Failed to read from client: %v\n", err)
				clientConn.Close()
				targetConn.Close()
				return
			}

			_, err = targetConn.Write(buf[:n])
			if err != nil {
				log.Printf("Failed to write to target server: %v\n", err)
				clientConn.Close()
				targetConn.Close()
				return
			}
		}
	}()

	// 获取目标的数据，将数据发送给客户端
	buf := make([]byte, 1024)
	for {
		n, err := targetConn.Read(buf)
		if err != nil {
			log.Printf("Failed to read from target server: %v\n", err)
			clientConn.Close()
			targetConn.Close()
			return
		}

		_, err = clientConn.Write(buf[:n])
		if err != nil {
			log.Printf("Failed to write to client: %v\n", err)
			clientConn.Close()
			targetConn.Close()
			return
		}
	}
}

func ToMap(m sync.Map) map[interface{}]interface{} {
	normalMap := make(map[interface{}]interface{})

	m.Range(func(key, value interface{}) bool {
		normalMap[key] = value
		// log.Println(key, value)
		return true
	})
	return normalMap
}

func GetIP() string {
	interfaces, err := net.Interfaces()
	if err != nil {
		fmt.Println("Error:", err)
		return "127.0.0.1"
	}

	for _, iface := range interfaces {
		addrs, err := iface.Addrs()
		if err != nil {
			fmt.Println("Error:", err)
			continue
		}

		for _, addr := range addrs {
			if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() && ipNet.IP.To4() != nil {
				return ipNet.IP.String()
			}
		}
	}
	return "127.0.0.1"
}

func GetLocalIp() {

}
